package winOrDie.GameEngine.RT.Server_Engine;

import java.awt.Dialog.ModalExclusionType;
import java.net.DatagramPacket;
import java.util.ArrayList;

import org.eclipse.swt.graphics.Point;

import winOrDie.Application.WoD_Application_Data;
import winOrDie.Game.WoD_Game;
import winOrDie.GameEngine.RT.mp.MapBoard;
import winOrDie.GameEngine.RT.mp.Mapping;
import winOrDie.Net.WoD_Net_Protocol_Manager;
import winOrDie.Net.Client.WoD_Client_RT_Event;
import winOrDie.Net.RT.WoD_RT_Client_Movement;
import winOrDie.Net.RT.WoD_RT_Game_Info;
import winOrDie.Net.RT.WoD_RT_NTP_Message;
import winOrDie.Net.Server.WoD_Server_Client;
import winOrDie.Net.Server.WoD_Server_Client_List;
import winOrDie.Net.Server.WoD_Server_RT;
import winOrDie.Net.Server.WoD_Server_RT_Event;
import winOrDie.Net.Server.WoD_Server_RT_Listener;
import winOrDie.graphics.maps.Map_Cell;
import winOrDie.graphics.maps.WoD_Map;
import winOrDie.graphics.maps.WoD_Map_Editor;

public class WoD_RT_Server_Engine 
implements WoD_Server_RT_Listener,
WoD_RT_Server_Engine_Bucket_Event_Processor
{

	
	private WoD_Server_RT woDServerRT = null;
	private WoD_Server_Client_List woDServerClientList = null;
	private WoD_RT_Server_Engine_Bucket bucket = null;
	
	private WoD_RT_Server_Engine_Movements_List movementsList = null;
	
	private WoD_Net_Protocol_Manager woDNetProtocolManager = null;
	
	
	private WoD_Map woDMap = null;
	private int Game_State = -1;
	
	/**
	 * This WoD_RT_Game_Info stores current player positions
	 */
	private WoD_RT_Game_Info woDRTGameInfo = null;
	
	
	public WoD_RT_Server_Engine_Movements_List getMovementsList() {
		return movementsList;
	}




	public WoD_RT_Server_Engine(
			WoD_Server_RT woDServerRT,
			WoD_Server_Client_List woDServerClientList,
			String mapName
			) throws Exception 
	{
		this.woDServerRT = woDServerRT;
		this.woDServerClientList = woDServerClientList;
		
		
		woDMap = WoD_Map_Editor.get_WoD_Map_From_File(
				"maps/" + mapName
				);
		
		/**
		 * Initial state
		 */
		Game_State = Mapping.RT_GAME_STATE.STARTED;
		
		woDRTGameInfo = new WoD_RT_Game_Info();
		
		/**
		 * Initialize WoD_Net_Protocol_Manager
		 */
		woDNetProtocolManager = new WoD_Net_Protocol_Manager();
		
		/**
		 * Initialize movements arraylist
		 */
		movementsList = new WoD_RT_Server_Engine_Movements_List();
		
		/**
		 * Initialize WoD_RT_Server_Engine_Bucket
		 */
		bucket = new WoD_RT_Server_Engine_Bucket(this);
		
		/**
		 * Add WoD_Server_RT Listener
		 */
		this.woDServerRT.add_WoD_Server_RT_Listener(this);
		
		
		
		
		
		
	}
	
	
	private void update_CurrentGameState(WoD_RT_Client_Movement clientMovement)
	{
		
		int player_position = -1;
		
		for (int position = 0; position < woDRTGameInfo.getClientMovements().size(); position++) {
			if (woDRTGameInfo.getClientMovements().get(position).getID() == clientMovement.getID())
			{
				player_position = position;
				
			}
		}
		
		if (player_position != -1)
		{
			woDRTGameInfo.getClientMovements().set(player_position, clientMovement);
		}
		else
		{
			woDRTGameInfo.getClientMovements().add(clientMovement);
		}
		
	}
	
	
	@Override
	public void processEvent(WoD_RT_Server_Engine_Bucket_Event event) {
		switch (event.getType()) {
		case WoD_RT_Server_Engine_Bucket_Event.MOVE:
			
			try {
				manage_Bucket_Event_Move(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;

		default:
			break;
		}
		
	}
	
	
	private void manage_Bucket_Event_Move(WoD_RT_Server_Engine_Bucket_Event event) throws Exception
	{
		WoD_RT_Client_Movement movement = (WoD_RT_Client_Movement)event.getData();
		
		int position = woDServerClientList.get_PositionOfClient_By_ID(movement.getID());
		if (position == -1)
		{
			Exception exception = new Exception("WoD Client with ID " + movement.getID() + " does not exists.");
			throw exception;
		}
		
		movementsList.add_WoD_RT_Client_Movement(movement);
		
	}




	@Override
		public void notify_Event_WoD_Server_RTChannel(WoD_Server_RT_Event event) {
			switch (event.getEvent_Type()) {
			case WoD_Server_RT_Event.GAME_ACTION:
				
				try {
	//				WoD_RT_Client_Movement movement = woDNetProtocolManager.parse_RT_Movement(datagramPacket.getData());
	//				WoD_RT_Server_Engine_Bucket_Event bucketEvent = new WoD_RT_Server_Engine_Bucket_Event(this, WoD_RT_Server_Engine_Bucket_Event.MOVE);
	//				bucketEvent.setData(movement);
	//				bucketEvent.setTs(movement.getTimeStamp());
					
					manage_RT_Message_GAME_ACTION(event);
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				
				break;
	
			default:
				break;
			}
			
		}




	private synchronized void manage_RT_Message_GAME_ACTION(WoD_Server_RT_Event event) throws Exception
	{
		DatagramPacket datagramPacket = (DatagramPacket)event.getData();
		WoD_RT_Client_Movement movement = woDNetProtocolManager.parse_RT_Movement(datagramPacket.getData());
		
		int position = woDServerClientList.get_PositionOfClient_By_ID(movement.getID());
		if (position == -1)
		{
			Exception exception = new Exception("WoD Client with ID " + movement.getID() + " does not exists.");
			throw exception;
		}
		
		/**
		 * Update current game state
		 */
		update_CurrentGameState(movement);
		
//		movementsList.add_WoD_RT_Client_Movement(movement);
	}
	
	
	
	private WoD_RT_Client_Movement get_Captain_Position()
	{
		
		for (WoD_RT_Client_Movement movement : woDRTGameInfo.getClientMovements()) {
			
			int position = woDServerClientList.get_PositionOfClient_By_ID(movement.getID());
			if ((position != -1) &&
					(woDServerClientList.getClients().get(position).getTeam() == WoD_Game.Game_Teams.Captain_Team) &&
					(woDServerClientList.getClients().get(position).getROL() == WoD_Game.Game_Rols.Captain)
					)
			{
				return movement;
			}

		}
		return null;
		
	}
	
	private ArrayList<WoD_RT_Client_Movement> get_Pirates_Position()
	{
		ArrayList<WoD_RT_Client_Movement> movements_Pirates = new ArrayList<WoD_RT_Client_Movement>(); 
		
		for (WoD_RT_Client_Movement movement : woDRTGameInfo.getClientMovements()) {
			int position = woDServerClientList.get_PositionOfClient_By_ID(movement.getID());
			if ((position != -1) && 
					(woDServerClientList.getClients().get(position).getTeam() == WoD_Game.Game_Teams.Pirates_Team))
			{
				movements_Pirates.add(movement);
			}
		}
		
		return movements_Pirates;
	}
	
	
	
	private boolean Check_CaptainCaptured(WoD_RT_Client_Movement captain_Position)
	{
		if (captain_Position == null){return false;}
		
		Point point_Captain = MapBoard.get_Casilla(captain_Position.getX(), captain_Position.getY());
		
		
		
		ArrayList<WoD_RT_Client_Movement> pirates_Positions = get_Pirates_Position();
		
		for (WoD_RT_Client_Movement pirate_Positon : pirates_Positions) {
			
			Point point_Pirate = MapBoard.get_Casilla(pirate_Positon.getX(), pirate_Positon.getY());
			
			if (point_Pirate.equals(point_Captain))
			{
				return true;
			}
		}
		
		return false;
	}
	
	
	private boolean Check_Princess_Free(WoD_RT_Client_Movement captain_Position)
	{
		if (captain_Position == null){return false;}
		
		Point point = MapBoard.get_Casilla(captain_Position.getX(), captain_Position.getY());
		
				
		try {
			if (woDMap.getMapBoard().get_Map_Cell(point.x, point.y).getType() == Map_Cell.Map_Cell_Type.Tower_Door)
			{
				return true;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	
	
	private boolean Check_Captain_Wins(WoD_RT_Client_Movement captain_Position)
	{
		if (captain_Position == null){return false;}
		Point point = MapBoard.get_Casilla(captain_Position.getX(), captain_Position.getY());
		
		
		try {
			if (woDMap.getMapBoard().get_Map_Cell(point.x, point.y).getType() == Map_Cell.Map_Cell_Type.Exit)
			{
				return true;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return false;
	}
	
	
	public synchronized void send_movements() throws Exception
	{
//		ArrayList<WoD_RT_Client_Movement> Last_movements = movementsList.get_Last_Movements_FromClients(woDServerClientList.getClients());
//		WoD_RT_Game_Info woDRTGameInfo = new WoD_RT_Game_Info();
//		woDRTGameInfo.setClientMovements(Last_movements);
		
		WoD_RT_Client_Movement captain_Position = get_Captain_Position();
		
		
		/**
		 * Check captain captured
		 */
		if (Check_CaptainCaptured(captain_Position))
		{
			Game_State = Mapping.RT_GAME_STATE.CAPTAIN_CAPTURED;
		}
		
		
		/**
		 * Check princess free
		 */
		if ((Game_State == Mapping.RT_GAME_STATE.STARTED) &&
				(Check_Princess_Free(captain_Position))
				)
		{
			Game_State = Mapping.RT_GAME_STATE.PRINCESS_OUT;
		}
		
		
		/**
		 * Check Captain Wins
		 */
		if ((Game_State == Mapping.RT_GAME_STATE.PRINCESS_OUT) &&
				(Check_Captain_Wins(captain_Position))
				)
		{
			Game_State = Mapping.RT_GAME_STATE.CAPTAIN_WINS;
		}
		
		/**
		 * Set Game state
		 */
		woDRTGameInfo.setGameState(Game_State);
		
		byte[] message = woDNetProtocolManager.get_Game_RT_Info(woDRTGameInfo);
		
		for (WoD_Server_Client client : woDServerClientList.getClients()) {
			woDServerRT.send_Message_To_Client(client, message);
			
		}
		
//		movementsList.remove_Old_Movements(2000L);
		
		
	}
	
}
